package com.msb.crm;

import com.alibaba.fastjson.JSON;
import com.msb.crm.base.ResultInfo;
import com.msb.crm.exceptions.AuthException;
import com.msb.crm.exceptions.NoLoginException;
import com.msb.crm.exceptions.ParamsException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;


/**
 * 全局异常统一处理
 */

@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {

    /**
     * 方法返回值类型
     *      视图
     *          JSON
     *      如何判断方法的返回类型
     *          如果方法级别配置了 @ResponseBody 注解，表示方法返回的JSON；
     *          反之：返回的是视图
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {


        //如果捕获的是未登录异常,则重定向到登录页面
        if (ex instanceof NoLoginException) {
            ModelAndView mv = new ModelAndView("redirect:/index");
            return mv;
        }


        //设置默认的异常处理
        ModelAndView mv = new ModelAndView();
        mv.setViewName("");
        mv.addObject("code", 400);
        mv.addObject("msg", "系统");


        //判断HandlerMethod
        if (handler instanceof HandlerMethod) {
            //类型转换
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //获取方法上的ResponseBody注解
            ResponseBody responseBody = handlerMethod.getMethod().getDeclaredAnnotation(ResponseBody.class);
            //判断ResponseBody注解是否存在

            if (null == responseBody) {
                //不存在就返回视图的情况
                if (ex instanceof ParamsException) {
                    ParamsException pe = (ParamsException) ex;
                    mv.addObject("code", pe.getCode());
                    mv.addObject("msg", pe.getMsg());
                }else if (ex instanceof AuthException) {
                    AuthException a = (AuthException) ex;
                    mv.addObject("code", a.getCode());
                    mv.addObject("msg", a.getMsg());
                }
                return mv;
            } else {
                //存在就是返回JSON数据的情况
                ResultInfo resultInfo = new ResultInfo();

                resultInfo.setCode(300);
                resultInfo.setMsg("系统异常，请重试！");

                //如果捕获的是自定义异常
                if (ex instanceof ParamsException) {
                    //先转为参数校验异常对象
                    ParamsException pe = (ParamsException) ex;
                    resultInfo.setCode(pe.getCode());
                    resultInfo.setMsg(pe.getMsg());
                }else  if (ex instanceof AuthException) {
                    //先转为认证校验异常对象
                    AuthException a = (AuthException) ex;
                    resultInfo.setCode(a.getCode());
                    resultInfo.setMsg(a.getMsg());
                }

                //设置响应类型和编码格式（响应JSON格式数据）
                response.setContentType("application/json;charset=utf-8");

                //得到输出流
                PrintWriter out = null;
                try {
                    out = response.getWriter();
                    //将对象转为JSON格式，通过输出流输出
                    out.write(JSON.toJSONString(resultInfo));
                    out.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (out != null) {
                        out.close();
                    }
                }
                return null;
            }
        }
        return mv;
    }
}
